<#include "macros.ftm" >
<#assign module_name=module.name>
<#assign module_namespace>
  <#lt>${module_name}<#if remoteClass.abstract>/abstracts</#if><#rt>
</#assign>
<#assign remoteClass_namepath>
  <#lt>${module_namespace}.${remoteClass.name}<#rt>
</#assign>
<#assign extends_name>
  <#if remoteClass.name=="MediaObject">
    <#lt>EventEmitter<#rt>
  <#elseif remoteClass.extends??>
    <#lt>${remoteClass.extends.name}<#rt>
  </#if>
</#assign>
<#if remoteClass.extends??>
  <#assign import_name=''>
  <#list module.imports as import>
    <#list import.module.remoteClasses as remoteClass>
      <#if remoteClass.name == extends_name>
        <#assign import_name=import.name>
        <#break>
      </#if>
    </#list>
    <#if import_name != ''>
      <#break>
    </#if>
  </#list>
  <#if import_name == ''>
    <#list module.remoteClasses as remoteClass>
      <#if remoteClass.name == extends_name>
        <#assign import_name=module_name>
        <#break>
      </#if>
    </#list>
  </#if>
  <#assign import_namespace>
    <#lt>${import_name}<#if remoteClass.extends.type.abstract>/abstracts</#if><#rt>
  </#assign>
</#if>
<#if remoteClass.abstract>abstracts/</#if>${remoteClass.name}.js
/* Autogenerated with Kurento Idl */

<#include "license.ftm" >

var inherits = require('inherits');

var kurentoClient = require('kurento-client');

var disguise = kurentoClient.disguise;

<#if remoteClass.methods?has_content || hasSetters(remoteClass)>
var checkType      = kurentoClient.checkType;
var ChecktypeError = checkType.ChecktypeError;

  <#if remoteClass.name=="MediaElement">
var checkArray = checkType.checkArray;
  </#if>
<#else>
var ChecktypeError = kurentoClient.checkType.ChecktypeError;
</#if>
<#if remoteClass.methods?has_content
  || remoteClass.properties?has_content
  || remoteClass.name=="Hub"
  || remoteClass.name=="MediaObject">

var Transaction = kurentoClient.TransactionsManager.Transaction;
</#if>
<#include "remoteClass_requires.ftm" >
<#if remoteClass.extends??>
  <#assign import_package="">
  <#list module.imports as import>
    <#list import.module.remoteClasses as remoteClass>
      <#if remoteClass.name == extends_name>
        <#assign import_package=import.module.code.api.js.nodeName>
        <#break>
      </#if>
    </#list>
    <#if import_package != "">
      <#break>
    </#if>
  </#list>

  <#if import_name == module_name>
var ${extends_name} = require('./<#if remoteClass.abstract != remoteClass.extends.type.abstract>abstracts/</#if>${extends_name}');
  <#elseif module_name=='core'
        || module_name=='elements'
        || module_name=='filters'>
var ${extends_name} = require('${import_package}').<#if remoteClass.extends.type.abstract>abstracts.</#if>${extends_name};
  <#else>
var ${extends_name} = kurentoClient.register.<#if remoteClass.extends.type.abstract>abstracts<#else>classes</#if>.${extends_name};
  </#if>
<#elseif remoteClass.name=="MediaObject">

var ${extends_name} = require('events').${extends_name};
</#if>
<#if remoteClass.methods?has_content
  || remoteClass.properties?has_content
  || remoteClass.name=="Hub"
  || remoteClass.name=="MediaObject">


function noop(error, result) {
  if (error) console.trace(error);

  return result
};
</#if>


/**
<#if remoteClass.constructor?? && remoteClass.constructor.doc??>
  <@docstring doc=remoteClass.constructor.doc namepath=remoteClass_namepath/>
 *
</#if>
<#if remoteClass.doc??>
 * @classdesc
  <@docstring doc=remoteClass.doc namepath=remoteClass_namepath indent=1/>
 *
</#if>
<#if remoteClass.abstract>
 * @abstract
</#if>
<#if remoteClass.extends??>
 * @extends module:${import_namespace}.${extends_name}
<#elseif remoteClass.name=="MediaObject">
 * @extends external:${extends_name}
</#if>
 *
 * @constructor module:${remoteClass_namepath}
<#if remoteClass.events?? && remoteClass.events?has_content>
 *
  <#list remoteClass.events?sort_by("name") as event>
 * @fires {@link module:${module_name}#event:${event.name} ${event.name}}
  </#list>
</#if>
 */
function ${remoteClass.name}(<#if remoteClass.name=="MediaPipeline">strict</#if>){<#if extends_name??>
  ${remoteClass.name}.super_.call(this);
</#if>
<#include "remoteClass_constructors.ftm" >};
<#if extends_name??>
inherits(${remoteClass.name}, ${extends_name});
</#if>
<#if remoteClass.properties?has_content>


//
// Public properties
//
  <#list remoteClass.properties?sort_by("name") as property>
    <#if property.name != "id">
      <#assign getPropertyName="get${property.name?cap_first}">
      <#assign setPropertyName="set${property.name?cap_first}">

/**
      <#if property.doc??>
        <@docstring doc=property.doc namepath=remoteClass_namepath/>
 *
      </#if>
 * @alias module:${remoteClass_namepath}#${getPropertyName}
 *
 * @param {module:${remoteClass_namepath}~${getPropertyName}Callback} [callback]
 *
 * @return {external:Promise}
 */
${remoteClass.name}.prototype.${getPropertyName} = function(callback){
      <@arguments/>
      <#if property.type.type.class.name == 'org.kurento.modulecreator.definition.RemoteClass'>
  if (usePromise) {
    var self = this;

    var promise = new Promise(function(resolve, reject) {

      function callback2(error, values) {
        resolve(values)
      }

     self._invoke(transaction, '${getPropertyName}', function(error, result) {
        if (error) return callback(error);

        self.emit('_describe', result, callback2);
      })
    });
    return promise;
  } else {
    return disguise(this._invoke(transaction, '${getPropertyName}', function(error, result) {
      if (error) return callback(error);

      this.emit('_describe', result, callback);
    }), this)
  }
      <#else>
  return disguise(this._invoke(transaction, '${getPropertyName}', callback), this)
      </#if>
};
/**
 * @callback module:${remoteClass_namepath}~${getPropertyName}Callback
 * @param {external:Error} error
 * @param {<#if property.type.isMap()>Object.<string, ${namepath(property.type.name)}><#else>${namepath(property.type.name)}</#if>} result
 */
      <#if !(property.final || property.readOnly)>

/**
        <#if property.doc??>
          <@docstring doc=property.doc namepath=remoteClass_namepath/>
 *
        </#if>
 * @alias module:${remoteClass_namepath}#${setPropertyName}
 *
 * @param {<#if property.type.isMap()>Object.<string, ${namepath(property.type.name)}><#else>${namepath(property.type.name)}</#if>} ${property.name}
 * @param {module:${remoteClass_namepath}~${setPropertyName}Callback} [callback]
 *
 * @return {external:Promise}
 */
${remoteClass.name}.prototype.${setPropertyName} = function(${property.name}, callback){
        <@arguments params=[property]/>
  return disguise(this._invoke(transaction, '${setPropertyName}', params, callback), this)
};
/**
 * @callback module:${remoteClass_namepath}~${setPropertyName}Callback
 * @param {external:Error} error
 */
      </#if>
    </#if>
  </#list>
</#if>
<#if remoteClass.methods?has_content>


//
// Public methods
//
  <#list remoteClass.methods?sort_by("name") as method>

    <#assign methodParams_name=[]>
    <#list method.params as param>
      <#assign methodParams_name=methodParams_name+[param.name]>
    </#list>
/**
    <#if method.doc??>
      <@docstring doc=method.doc namepath=remoteClass_namepath/>
 *
    </#if>
 * @alias module:${remoteClass_namepath}.${method.name}
    <#list method.params as param>
 *
 * @param <@paramType param=param/>
      <@docstring doc=param.doc namepath=remoteClass_namepath indent=1/>
    </#list>
 *
 * @param {module:${remoteClass_namepath}~${method.name}Callback} [callback]
 *
 * @return {external:Promise}
 */
${remoteClass.name}.prototype.${method.name} = function(<@join sequence=(methodParams_name + ["callback"]) separator=", "/>){
    <#if method.return?? && method.return.type.type.class.name == 'org.kurento.modulecreator.definition.RemoteClass'>
      <@arguments params=method.params/>
  return disguise(this._invoke(transaction, '${method.name}'<#if method.params?has_content>, params</#if>, function(error, result)
  {
    if (error) return callback(error);

    this.emit('_describe', result, callback);
  }), this)
    <#elseif remoteClass.name == 'MediaElement' && method.name == 'connect'>
  var transaction = (arguments[0] instanceof Transaction)
                  ? Array.prototype.shift.apply(arguments)
                  : undefined;

  var promise
  if(sink instanceof Array)
  {
    callback = arguments[arguments.length-1] instanceof Function
             ? Array.prototype.pop.call(arguments)
             : undefined;

    var media = sink
    var src = this;
    sink = media[media.length-1]

    // Check if we have enought media components
    if(!media.length)
      throw new SyntaxError('Need at least one media element to connect');

    // Check MediaElements are of the correct type
    checkArray('MediaElement', 'media', media)

    // Generate promise
    promise = new Promise(function(resolve, reject)
    {
      function callback(error, result)
      {
        if(error) return reject(error);

        resolve(result);
      };

      each(media, function(sink, callback)
      {
        src = src.connect(sink, callback);
      },
      callback);
    });

    promise = promiseCallback(promise, callback)
  }
  else
  {
      <@arguments params=method.params/>
    promise = this._invoke(transaction, '${method.name}'<#if method.params?has_content>, params</#if>, callback)
  }

  return disguise(promise, sink)
    <#else>
      <@arguments params=method.params/>
  return disguise(this._invoke(transaction, '${method.name}'<#if method.params?has_content>, params</#if>, callback), this)
    </#if>
};
/**
 * @callback module:${remoteClass_namepath}~${method.name}Callback
 * @param {external:Error} error
    <#if method.return??>
 * @param {<#if method.return.type.isMap()>Object.<string, ${namepath(method.return.type.name)}><#else>${namepath(method.return.type.name)}</#if>} result
      <@docstring doc=method.return.doc namepath=remoteClass_namepath indent=1/>
    </#if>
 */
  </#list>
</#if>

<#include "remoteClass_prototypes.ftm">

/**
 * @alias module:${remoteClass_namepath}.constructorParams
<#if remoteClass.constructor??>
  <#list remoteClass.constructor.params?sort_by("name") as param>
 *
 * @property <@paramType param=param/>
    <@docstring doc=param.doc namepath=remoteClass_namepath indent=1/>
  </#list>
</#if>
 */
${remoteClass.name}.constructorParams = {
<#list (remoteClass.constructor.params?sort_by("name"))![] as param>
  ${param.name}: {
    type: '${param.type.type.qualifiedName}'<#if param.type.isList() || !param.optional>,
    <#if param.type.isList()>
    isArray: true<#if !param.optional>,</#if>
    </#if>
    <#if !param.optional>
    required: true
    </#if>
  </#if>
  }<#if param_has_next>,</#if>
</#list>
};

/**
 * @alias module:${remoteClass_namepath}.events
<#if remoteClass.extends??>
 *
 * @extends module:${import_namespace}.${extends_name}.events
</#if>
 */
<#assign remoteClassEvents_name=[]>
<#list remoteClass.events?sort_by("name") as event>
  <#assign remoteClassEvents_name=remoteClassEvents_name+["'"+event.name+"'"]>
</#list>
<#if remoteClass.extends??>
${remoteClass.name}.events = ${extends_name}.events<#if remoteClassEvents_name?has_content>.concat([<@join sequence=remoteClassEvents_name separator=", "/>])</#if>;
<#else>
${remoteClass.name}.events = [<@join sequence=remoteClassEvents_name separator=", "/>];
</#if>


/**
 * Checker for {@link module:${remoteClass_namepath}}
 *
 * @memberof module:${module_namespace}
 *
 * @param {external:String} key
 * @param {module:${remoteClass_namepath}} value
 */
function check${remoteClass.name}(key, value)
{
  if(!(value instanceof ${remoteClass.name}))
    throw ChecktypeError(key, ${remoteClass.name}, value);
};


module.exports = ${remoteClass.name};

${remoteClass.name}.check = check${remoteClass.name};
